﻿using MagicSir.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace MagicSir.MagicOptions
{
    internal static class MagicOptionsExtensions
    {
        public static IServiceCollection AddMagicOptions(this IServiceCollection services)
        {

            services.AddOptions();
            InjectOptions(services);

            return services;
        }

        static IEnumerable<Type> GetOptionTypes()
        {
            var types = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                        where assembly.ExportedTypes.Any(t =>

                          t.IsInterface == false
                          && t.IsAbstract == false
                          && typeof(IMagicOptions).IsAssignableFrom(t)
                        )
                        from type in assembly.ExportedTypes
                        where type.IsAbstract == false && type.IsInterface == false && typeof(IMagicOptions).IsAssignableFrom(type)
                        select type;
            return types.Distinct();
        }
        internal static IConfigurationRoot LoadConfig()
        {

            var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory());
            var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.json");

            foreach (var file in files)
            {
                builder.AddJsonFile(file);

            }
            return builder.Build();
        }
        static void InjectOptions(IServiceCollection services)
        {


            var type = typeof(OptionsServiceCollectionExtensions);

            var types = GetOptionTypes();
            foreach (var t in types)
            {
                InjectOptions(services, t);
            }

        }
        static void InjectOptions(IServiceCollection services, Type type)
        {
            var cfg = LoadConfig();

            var methodInfo = typeof(OptionsConfigurationServiceCollectionExtensions).GetMethod("Configure", 1, new Type[]
             {
                        typeof(IServiceCollection),
                        typeof(IConfiguration)
             });
            var match = Regex.Match(type.Name, @"^(?<name>\w+)(Options?)$"/*, RegexOptions.IgnoreCase*/);
            IConfigurationSection sec = match.Success ? cfg.GetSection(match.Groups["name"].Value) : cfg.GetSection(type.Name);

            if (sec != null)
            {

                var method = methodInfo.MakeGenericMethod(new Type[] { type });
                method.Invoke(null, new object[] { services, sec });
            }
        }
    }

}
